<script setup lang='ts'>
import { getHallChat, getTeamChat, getUserChat } from '@/api/chat';
import { getCurrentUser } from '@/api/user';
import { baseURL } from '@/request/myAxios';
import { showFailToast, showToast } from 'vant';
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';


const router = useRouter()
const route = useRoute()
const stats = ref({
  user: {
      id: 0,
      username: "",
      avatarUrl: ''
  },
  isCollapse: false,
  users: [],
  chatUser: {
      id: 0,
      username: ''
  },
  chatType: 0,
  team: {
      teamId: 0,
      teamName: ''
  },
  text: "",
  messages: [],
  content: ''
})
const chatEnum = {
  // 私信
  PRIVATE_CHAT: 1,
  // 队伍聊天
  TEAM_CHAT: 2,
  // 大厅
  HALL_CHAT: 3
}
const chatRoom = ref()
let {id, username, userType, teamId, teamName, teamType} = route.query
stats.value.chatUser.id = Number(id)
stats.value.team.teamId = Number(teamId)
stats.value.chatUser.username = String(username)
stats.value.team.teamName = String(teamName)
// 判断聊天室类型
const title = ref()
if(Number(userType) === chatEnum.PRIVATE_CHAT){
  title.value = String(username)
  stats.value.chatType = chatEnum.PRIVATE_CHAT
}else if(Number(teamType) === chatEnum.TEAM_CHAT){
  title.value = String(teamName)
  stats.value.chatType = chatEnum.TEAM_CHAT
}else{
  title.value = '官方聊天室'
  stats.value.chatType = chatEnum.HALL_CHAT
}
// 根据聊天室类型获取对应的聊天信息
const chat = ref()
// 获取初始化信息
const getChatInfo = async () => {
  const resp = await getCurrentUser()
  stats.value.user = resp.data.data
  const res = ref()
  // 队伍
  if(stats.value.chatType === chatEnum.TEAM_CHAT){
    res.value = await getTeamChat(stats.value.team.teamId)
    chat.value = res.value.data.data
    chat.value.forEach((chat: { isMy: any; fromUser: any; text: any; isAdmin: any; createTime: any; }) => {
      if(chat.isMy){
        createContent(null,chat.fromUser,chat.text,chat.isAdmin,chat.createTime)
      }else{
        createContent(chat.fromUser,null,chat.text,chat.isAdmin,chat.createTime)
      }
    })
  }
  // 私信
  if(stats.value.chatType === chatEnum.PRIVATE_CHAT){
    res.value = await getUserChat(stats.value.chatUser.id)
    chat.value = res.value.data.data
    chat.value.forEach((chat: {
        isMy: any; fromUser: {
          /* __placeholder__ */
          avatarUrl:
          /* __placeholder__ */
          any;
        } | null; text: any; isAdmin: any; createTime: any; toUser: {
          /* __placeholder__ */
          avatarUrl:
          /* __placeholder__ */
          any;
          /* __placeholder__ */
          username:
          /* __placeholder__ */
          any;
        } | null;
      }) => {
      if(chat.isMy){
        createContent(null,chat.fromUser,chat.text,chat.isAdmin,chat.createTime)
      }else{
        createContent(chat.toUser,null,chat.text,chat.isAdmin,chat.createTime)
      }
    })
  }
  // 大厅
   if(stats.value.chatType === chatEnum.HALL_CHAT){
    res.value = await getHallChat()
    chat.value = res.value.data.data
    chat.value.forEach((chat: { isMy: any; fromUser: any; text: any; isAdmin: any; createTime: any; }) => {
      if(chat.isMy){
        createContent(null,chat.fromUser,chat.text,chat.isAdmin,chat.createTime)
      }else{
        createContent(chat.fromUser,null,chat.text,chat.isAdmin,chat.createTime)
      }
    })
  }
  init()
  // 在数据更新之后,获得最新DOM状态之后执行
  await nextTick(() => {
    chatRoom.value.lastElementChild?.scrollIntoView()
  })

}
onMounted(() =>{ 
  getChatInfo()
  
})
// 离开组件关闭定时器
onUnmounted(() => stopHeartbeat())

// 初始化websocket
let socket: WebSocket | null = null;
const heartbeatInterval = 30 * 1000; // 30秒
let heartbeatTimer:any = null;
// 定时发送心跳包pong
const startHeartbeat = () => {
    heartbeatTimer = setInterval(() => {
        if (socket?.readyState === WebSocket.OPEN) {
            socket.send("PING");
        }
    }, heartbeatInterval);
}
// 关闭定时器心跳包
const stopHeartbeat = () => {
    clearInterval(heartbeatTimer);
    heartbeatTimer = null;
}
// 初始化webScoket
const init = () => {
  let userId = stats.value.user.id
  let socketUrl =  'ws://' + baseURL + '/websocket/' + userId + '/' + stats.value.team.teamId
  if(socket != null){
    socket.close()
  }
  // 开启一个webSocket
  socket = new WebSocket(socketUrl)
  // 开始时调用
  socket.onopen = () => {
    startHeartbeat()
  }
  // 在接收到消息时
  socket.onmessage = (msg) => {
    if(msg.data === 'pong'){
      return
    }
    let data = JSON.parse(msg.data)
    if(data.error){
      showFailToast(data.error)
      return
    }
    if(data.users){
      stats.value.users = data.users.filter((user: { id: number; }) => {
        return user.id !== userId
      })
    }else{
      let flag;
      if(stats.value.chatType === data.chatType){
        flag = (data.fromUser?.id != userId)
      }
      if(flag){
        stats.value.messages.push(data)
        createContent(data.fromUser,null,data.text,data.isAdmin,data.createTime)
      }
      nextTick(() => {
        chatRoom.value.lastElementChild?.scrollIntoView()
      })
      flag = null
    }
  }
  // 关闭时
  socket.onclose = () => {
    stopHeartbeat()
  }
  // 发生错误时
  socket.onerror = () => {
    showFailToast('系统发生错误！')
  }
}
// 创建消息
const createContent = (remoteUser: { avatarUrl: any; username: any; id:any } | null, nowUser: { avatarUrl: any; } | null, text: any, isAdmin: any, createTime: any) => {
  let content;
  if(remoteUser){
    content = `
      <div class="message">
        <img
          src="${remoteUser.avatarUrl}"
          class="avatar"
          onclick='toUserDetail(${remoteUser.id})'
        />
        <div class="chat-content">
          <div style="display: flex; align-items: center;">
            <span onclick='toUserDetail(${remoteUser.id})' class="username">${remoteUser.username}</span>
            <span class="time">${createTime}</span>
          </div>
          <p class="chat_text other">${text}</p>
        </div>
      </div>
    `
  }else if(nowUser){
    content = `
      <div class="message self">
        <img
          src="${nowUser.avatarUrl}"
          class="avatar"
          style="order: 2;"
        />
        <div class="mychat">
          <p class="chat_text self" style="background-color: #95ec69;">${text}</p>
        </div>
      </div>
    `
  }
  stats.value.content += content
}
// 去用户详情页面
const toUserDetail = (id: any) => {
  router.push({
    path: '/user/detail',
    query: {
      id
    }
  })
}
window.toUserDetail = toUserDetail
// 发送消息
const send = () => {
  if (stats.value.chatUser.id === 0) {
        return;
  }
  if (stats.value.chatUser.id === stats.value.user.id) {
      showFailToast("不能给自己发信息")
      return;
  }
  if(!stats.value.text.trim()){
    showToast('请输入内容')
  }else{
    let message = {
      chatType: stats.value.chatType,
      fromId: stats.value.user.id,
      text: stats.value.text,
      teamId: stats.value.team.teamId,
      toId: stats.value.chatUser.id
    }
    socket?.send(JSON.stringify(message))
    stats.value.messages.push({user: stats.value.user.id, text: stats.value.text})
    createContent(null,stats.value.user,stats.value.text,null,null)
    stats.value.text = ''
    nextTick(() => {
      chatRoom.value.lastElementChild?.scrollIntoView()
    })
  }
}
</script>
<template>
  <van-sticky>
        <van-nav-bar
            :title="title"
            left-arrow
            @click-left="$router.back()"
        >
        </van-nav-bar>
    </van-sticky>
    <article class="chat" ref="chatRoom" v-html="stats.content">

    </article>
    <footer class="footer">
      <van-cell-group inset>
        <van-field
          style="width: 100%;"
          v-model="stats.text"
          center
          clearable
          rows="1"
          autosize
          type="textarea"
          placeholder="聊点什么"
        >
          <template #button>
            <van-button @click="send"size="small" type="primary">发送</van-button>
          </template>
        </van-field>
      </van-cell-group>
    </footer>
</template>
<style>
.chat{
  width: 100%;
  margin-bottom: 50px;
  display: flex;
  flex-direction: column
}
.message{
  display: flex;
  margin: 10px;
}
.self{
  align-self: flex-end;
}
.avatar{
  height: 40px;
  width: 40px;
  border-radius: 50%;
}

.chat-content{
  margin-left: 10px;
  display: flex;
  flex-direction: column;
  
}
.username{
  color: #8f8f8f;
  font-size: 15px;
}
.time{
  color: #8f8f8f;
  font-size: 10px;
  margin-left: 10px;
}
.chat_text { 
  margin: 5px;
  background-color: #ededed;
  padding: 10px;
  border-radius: 10px;
  word-wrap:break-word;
  word-break:break-all;
}
.mychat{
  margin-right: 10px;
}
.other{
  align-self: self-start;
}
.footer{
  position: fixed;
  bottom: 0;
  height: 50px;
  width: 100%;
  display: flex;
  align-items: center;
}
.van-cell-group{
  margin: 0;
}

</style>
<style scoped>
.van-cell-group--inset{
  height: 100%;
  width: 100%;
  margin: 0 !important;
  padding-bottom: 15px;
}
</style>
